/**
 * 
 */
package component.lucene;

import static java.lang.System.out;

import java.io.File;
import java.io.IOException;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.Index;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.Field.TermVector;
import org.apache.lucene.document.Fieldable;
import org.apache.lucene.document.NumericField;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.NumericRangeFilter;
import org.apache.lucene.search.NumericRangeQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.util.Version;

/**
 * @author liuboen
 * {@link boengood@gmail.com}
 */
public class LuceneDemo {
	public static final String[] contents = { "中国", "中国人", "中华人民共和国", "china",
		"美国", "美利坚共和国", "American", "中国资产阶级", "美国政治", "美国政治脱口秀", "黄西脱口秀", "麦当娜",
		"迈克尔.杰克逊" };
	
	private Directory directory = null;
	private  IndexSearcher searcher = null;
	private Analyzer analyzer = null;
	
	LuceneDemo(Boolean isIndex){
		//初始化索引存储
		//directory = new RAMDirectory();
		try {
			directory = FSDirectory.open(new File("D:\\lucenetest\\index"));
		} catch (IOException e) {
			e.printStackTrace();
		}
		//初始化分词器
		analyzer = new StandardAnalyzer(Version.LUCENE_35);
		//analyzer = new IKAnalyzer();
		
		if (isIndex) {
			index();
		}
		try {
			searcher = new  IndexSearcher(IndexReader.open(directory));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}


	
	/**
	 * 创建索引
	 */
	public void index(){
		//索引写入配置
		IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_35, analyzer);
		try {
			IndexWriter writer = new IndexWriter(directory, indexWriterConfig);
			int sort = 1;
			for (String content: contents) {
				//新建一条记录,lucene里面采用document 作为一条搜索记录
				Document doc = new Document();
				//新建普通字段
				Fieldable  filed = new Field("title", content,  Store.YES, Index.ANALYZED, TermVector.YES);
				Fieldable  filed2 = new Field("type", "type",  Store.YES, Index.ANALYZED, TermVector.YES);
				//设置权重,默认为1,大于1时代表权重越高
				filed.setBoost(100F);
				//新建用于排序字段
				NumericField  numericField = new NumericField("sort",Store.YES,Boolean.TRUE).setIntValue(sort);
				doc.add(filed);
				doc.add(filed2);
				doc.add(numericField);
				writer.addDocument(doc);
				sort++;
			}
			writer.close();
		} catch (CorruptIndexException e) {
			e.printStackTrace();
		} catch (LockObtainFailedException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 普通文本搜索
	 * @param queryString
	 */
	public void search(String queryString){
		try {
			 QueryParser parser = new QueryParser(Version.LUCENE_35, "title", analyzer);
			 Query query = parser.parse(queryString);
			 //查询结果集TOP
			 TopDocs results = searcher.search(query, 10000);
			 ScoreDoc[] hits = results.scoreDocs;
			 //获取查询总数
			 int numTotalHits = results.totalHits;
			 out.println(numTotalHits + " total matching documents");
			 
			 for (ScoreDoc scoreDoc : hits) {
				  Document doc = searcher.doc(scoreDoc.doc);
				  out.println(scoreDoc.toString());
				  out.println("title is : " + doc.get("title"));
				  out.println("sort is : " + doc.get("sort"));
			}
		} catch (ParseException e) {
			e.printStackTrace();
		}catch (IOException e) {
			e.printStackTrace();
		}
	}
	/**
	 * 普通文本搜索
	 * @param queryString
	 */
	public void searchTerm(String queryString ,String term){
		try {
			BooleanQuery booleanQuery= new BooleanQuery();
			
			QueryParser parser = new QueryParser(Version.LUCENE_35, "title", analyzer);
			Query query = parser.parse(queryString);
			// 指定term查询
			Query queryTerm = new TermQuery(new Term("type", term));
			 
			// 将两个查询条件添加到booleanQuery
			booleanQuery.add(query, BooleanClause.Occur.MUST);
			booleanQuery.add(queryTerm, BooleanClause.Occur.MUST);

			//查询结果集TOP
			TopDocs results = searcher.search(booleanQuery, 10000);
			ScoreDoc[] hits = results.scoreDocs;
			//获取查询总数
			int numTotalHits = results.totalHits;
			out.println(numTotalHits + " total matching documents");
			
			for (ScoreDoc scoreDoc : hits) {
				Document doc = searcher.doc(scoreDoc.doc);
				out.println(scoreDoc.toString());
				out.println("title is : " + doc.get("title"));
				out.println("sort is : " + doc.get("sort"));
			}
		} catch (IOException e) {
			e.printStackTrace();
		}catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
	
	/**
	 * 查询数字类型区间
	 * @param queryString
	 */
	public void searchNumericRange(String queryString){
		try {
			BooleanQuery booleanQuery= new BooleanQuery();
			
			QueryParser parser = new QueryParser(Version.LUCENE_35, "title", analyzer);
			Query query = parser.parse(queryString);
			//新建数值类型区间
			NumericRangeQuery<Integer> termRangeQuery = NumericRangeQuery.newIntRange("sort", 1, 5, Boolean.TRUE, Boolean.TRUE);
			
			// 将两个查询条件添加到booleanQuery
			booleanQuery.add(query, BooleanClause.Occur.MUST);
			booleanQuery.add(termRangeQuery, BooleanClause.Occur.MUST);
			
			//查询结果集TOP
			TopDocs results = searcher.search(booleanQuery, 10000);
			ScoreDoc[] hits = results.scoreDocs;
			int numTotalHits = results.totalHits;
			out.println(numTotalHits + " total matching documents");
			
			for (ScoreDoc scoreDoc : hits) {
				Document doc = searcher.doc(scoreDoc.doc);
				out.println(scoreDoc.toString());
				out.println("title is : " + doc.get("title"));
				out.println("sort is : " + doc.get("sort"));
			}
		} catch (ParseException e) {
			e.printStackTrace();
		}catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 将结果集排序
	 * @param queryString
	 */
	public void searchSort(String queryString){
		try {
			QueryParser parser = new QueryParser(Version.LUCENE_35, "title", analyzer);
			Query query = parser.parse(queryString);
			
			// 新建排序
			Sort sort = new Sort();
			sort.setSort(new SortField("sort", SortField.INT, Boolean.FALSE));

			// 查询结果集TOP
			TopDocs results = searcher.search(query, 10000,sort);
			ScoreDoc[] hits = results.scoreDocs;
			int numTotalHits = results.totalHits;
			out.println(numTotalHits + " total matching documents");
			
			for (ScoreDoc scoreDoc : hits) {
				Document doc = searcher.doc(scoreDoc.doc);
				out.println(scoreDoc.toString());
				out.println("title is : " + doc.get("title"));
				out.println("sort is : " + doc.get("sort"));
			}
		} catch (ParseException e) {
			e.printStackTrace();
		}catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 查询出来后通过过滤结果集
	 * @param queryString
	 */
	public void searchFilter(String queryString){
		try {
			QueryParser parser = new QueryParser(Version.LUCENE_35, "title", analyzer);
			Query query = parser.parse(queryString);
			// 新建过滤器
			NumericRangeFilter<?> filter = NumericRangeFilter.newIntRange("sort", 1, 5, Boolean.TRUE, Boolean.TRUE);
			//查询结果集TOP
			TopDocs results = searcher.search(query,filter,100000);
			ScoreDoc[] hits = results.scoreDocs;
			int numTotalHits = results.totalHits;
			out.println(numTotalHits + " total matching documents");
			
			for (ScoreDoc scoreDoc : hits) {
				Document doc = searcher.doc(scoreDoc.doc);
				out.println(scoreDoc.toString());
				out.println("title is : " + doc.get("title"));
				out.println("sort is : " + doc.get("sort"));
			}
		} catch (ParseException e) {
			e.printStackTrace();
		}catch (IOException e) {
			e.printStackTrace();
		}
	}
	

	public static void main(String a[]) {
		LuceneDemo test = new LuceneDemo(Boolean.FALSE);
		/*
		 * Scanner cin = new Scanner (new BufferedInputStream(System.in));
		 * String next = cin.next(); out.print(next);
		 */
		String queryString = "中国";
		test.search(queryString);
		out.println("-------------------------------------------------------");
		test.searchTerm(queryString , "type");
		out.println("-------------------------------------------------------");
		test.searchNumericRange(queryString);
		out.println("-------------------------------------------------------");
		test.searchSort(queryString);
		out.println("-------------------------------------------------------");
		test.searchFilter(queryString);
	}
}
